package com.uduemc.biso.node.web.api.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.github.pagehelper.PageInfo;
import com.uduemc.biso.core.extities.node.custom.LoginNode;
import com.uduemc.biso.core.utils.JsonResult;
import com.uduemc.biso.core.utils.RestResult;
import com.uduemc.biso.core.utils.ResultUtil;
import com.uduemc.biso.node.core.common.feign.CProductFeign;
import com.uduemc.biso.node.core.dto.FeignFindInfoBySystemProductIds;
import com.uduemc.biso.node.core.dto.FeignSystemTotal;
import com.uduemc.biso.node.core.entities.SProduct;
import com.uduemc.biso.node.core.entities.SProductLabel;
import com.uduemc.biso.node.core.entities.SSeoItem;
import com.uduemc.biso.node.core.entities.SSystem;
import com.uduemc.biso.node.core.entities.custom.CategoryQuote;
import com.uduemc.biso.node.core.entities.custom.Product;
import com.uduemc.biso.node.core.entities.custom.ProductDataTableForList;
import com.uduemc.biso.node.core.entities.custom.RepertoryQuote;
import com.uduemc.biso.node.core.feign.SProductFeign;
import com.uduemc.biso.node.core.feign.SProductLabelFeign;
import com.uduemc.biso.node.core.node.dto.FeignProductTableData;
import com.uduemc.biso.node.core.node.extities.ProductTableData;
import com.uduemc.biso.node.core.node.feign.NProductFeign;
import com.uduemc.biso.node.core.utils.RestResultUtil;
import com.uduemc.biso.node.web.api.component.RequestHolder;
import com.uduemc.biso.node.web.api.dto.RequestProduct;
import com.uduemc.biso.node.web.api.dto.RequestProductTableDataList;
import com.uduemc.biso.node.web.api.dto.item.ItemCustomLink;
import com.uduemc.biso.node.web.api.service.LoginService;
import com.uduemc.biso.node.web.api.service.ProductService;
import com.uduemc.biso.node.web.api.service.SystemItemCustomLinkService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class ProductServiceImpl implements ProductService {

    @Resource
    private SProductFeign sProductFeign;

    @Resource
    private SProductLabelFeign sProductLabelFeign;

    @Resource
    private CProductFeign cProductFeign;

    @Resource
    private NProductFeign nProductFeign;

    @Resource
    private RequestHolder requestHolder;

    @Resource
    private SystemItemCustomLinkService systemItemCustomLinkServiceImpl;

    @Resource
    private LoginService loginServiceImpl;

    @Override
    public boolean existByHostSiteIdAndId(long hostId, long siteId, long id)
            throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        return false;
    }

    @Override
    public boolean existCurrentById(long id) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        return false;
    }

    @Override
    public boolean existCurrentBySystemIdAndId(long id, long systemId) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        Long hostId = requestHolder.getHost().getId();
        Long siteId = requestHolder.getCurrentSite().getId();
        RestResult restResult = sProductFeign.findByHostSiteSystemIdAndId(hostId, siteId, systemId, id);
        SProduct data = RestResultUtil.data(restResult, SProduct.class);
        return !(data == null);
    }

    @Override
    public Product save(RequestProduct requestProduct) throws JsonProcessingException, IOException {
        Product product = new Product();

        SProduct sProduct = requestProduct.makeSProduct(requestHolder);
        product.setSProduct(sProduct);

        List<CategoryQuote> listCategoryQuote = requestProduct.makeListCategoryQuote(requestHolder);
        product.setListCategoryQuote(listCategoryQuote);

        List<RepertoryQuote> listImageListFace = requestProduct.makeListImageListFace(requestHolder);
        product.setListImageListFace(listImageListFace);

        List<RepertoryQuote> listImageListInfo = requestProduct.makeListImageListInfo(requestHolder);
        product.setListImageListInfo(listImageListInfo);

        List<RepertoryQuote> listFileListInfo = requestProduct.makeListFileListInfo(requestHolder);
        product.setListFileListInfo(listFileListInfo);

        List<SProductLabel> listLabelContent = requestProduct.makeListLabelContent(requestHolder);
        product.setListLabelContent(listLabelContent);

        SSeoItem sSeoItem = requestProduct.makeSSeoItem(requestHolder);
        product.setSSeoItem(sSeoItem);

        Product data = null;
        if (product.getSProduct().getId() == null || product.getSProduct().getId().longValue() < 1) {
            // 新增
            RestResult restResult = cProductFeign.insert(product);
            data = RestResultUtil.data(restResult, Product.class);

            if (data != null && data.getSProduct() != null) {
                // 记录新增情况下的产品使用的分类
                List<Long> categoryIds = CollUtil.isEmpty(data.getListCategoryQuote()) ? null : data.getListCategoryQuote().stream().map(item -> item.getSCategories().getId()).collect(Collectors.toList());
                LoginNode loginNode = requestHolder.getCurrentLoginNode();
                loginNode.saveSystemCategory(data.getSProduct().getSystemId(), categoryIds);
                loginServiceImpl.recacheLoginNode(loginNode);
            }

        } else {
            // 修改
            RestResult restResult = cProductFeign.update(product);
            data = RestResultUtil.data(restResult, Product.class);
        }

        if (data != null) {
            ItemCustomLink customLink = requestProduct.getItemCustomLink();
            if (customLink != null) {
                makeCustomLink(data, customLink);
            } else {
                // 删除动作
                systemItemCustomLinkServiceImpl.deleteByHostSiteSystemItemId(data.getSProduct().getHostId(), data.getSProduct().getSiteId(),
                        data.getSProduct().getSystemId(), data.getSProduct().getId());
            }
        }

        return data;
    }

    @Override
    public Product infoCurrentByProductId(long productId) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = cProductFeign.findByHostSiteProductId(requestHolder.getHost().getId(), requestHolder.getCurrentSite().getId(), productId);
        Product data = RestResultUtil.data(restResult, Product.class);
        makeCustomLink(data);
        return data;
    }

    @Override
    public PageInfo<ProductTableData> getInfosByRequestProductTableDataList(RequestProductTableDataList requestProductTableDataList)
            throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        FeignProductTableData feignProductTableData = requestProductTableDataList.getFeignProductTableData(requestHolder);
        feignProductTableData.setIsRefuse((short) 0);

        RestResult restResult = nProductFeign.tableDataList(feignProductTableData);
        @SuppressWarnings("unchecked")
        PageInfo<ProductTableData> data = (PageInfo<ProductTableData>) RestResultUtil.data(restResult, new TypeReference<PageInfo<ProductTableData>>() {
        });
        return data;
    }

    @Override
    public PageInfo<ProductTableData> getRecycleInfosByRequestProductTableDataList(RequestProductTableDataList requestProductTableDataList)
            throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        FeignProductTableData feignProductTableData = requestProductTableDataList.getFeignProductTableData(requestHolder);
        feignProductTableData.setIsRefuse((short) 1);

        RestResult restResult = nProductFeign.tableDataList(feignProductTableData);
        @SuppressWarnings("unchecked")
        PageInfo<ProductTableData> data = (PageInfo<ProductTableData>) RestResultUtil.data(restResult, new TypeReference<PageInfo<ProductTableData>>() {
        });
        return data;
    }

    @Override
    public boolean updateBySProduct(SProduct sProduct) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = sProductFeign.updateById(sProduct);
        SProduct data = RestResultUtil.data(restResult, SProduct.class);
        return data != null;
    }

    @Override
    public boolean deletes(List<SProduct> listSProduct) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = cProductFeign.deleteByListSProduct(listSProduct);
        return RestResultUtil.data(restResult, Boolean.class);
    }

    @Override
    public boolean existLabelByIdAndHostSiteId(long id, long hostId, long siteId)
            throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = sProductLabelFeign.existByHostSiteIdAndId(hostId, siteId, id);
        Boolean data = RestResultUtil.data(restResult, Boolean.class);
        return data;
    }

    @Override
    public boolean existLabelCurrentById(long id) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        return existLabelByIdAndHostSiteId(id, requestHolder.getHost().getId(), requestHolder.getCurrentSite().getId());
    }

    @Override
    public SProduct getCurrentSProductById(long id) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = sProductFeign.findByHostSiteIdAndId(requestHolder.getHost().getId(), requestHolder.getCurrentSite().getId(), id);
        SProduct data = RestResultUtil.data(restResult, SProduct.class);
        return data;
    }

    @Override
    public PageInfo<ProductDataTableForList> infosCurrentBySystemCategoryIdAndPageLimit(long systemId, long categoryId, String name, int page, int limit)
            throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        Long hostId = requestHolder.getHost().getId();
        Long siteId = requestHolder.getCurrentSite().getId();
        return infosByHostSiteSystemCategoryIdAndPageLimit(hostId, siteId, systemId, categoryId, name, page, limit);
    }

    @Override
    public PageInfo<ProductDataTableForList> infosByHostSiteSystemCategoryIdAndPageLimit(long hostId, long siteId, long systemId, long categoryId, String name,
                                                                                         int page, int limit) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = cProductFeign.findInfosByHostSiteSystemCategoryIdNameAndPageLimit(hostId, siteId, systemId, categoryId, name, page, limit);
        @SuppressWarnings("unchecked")
        PageInfo<ProductDataTableForList> data = (PageInfo<ProductDataTableForList>) RestResultUtil.data(restResult,
                new TypeReference<PageInfo<ProductDataTableForList>>() {
                });
        return data;
    }

    @Override
    public ProductDataTableForList infoCurrentBySystemProductId(long systemId, long pid)
            throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = cProductFeign.findInfoBySystemProductId(requestHolder.getHost().getId(), requestHolder.getCurrentSite().getId(), systemId, pid);
        ProductDataTableForList data = RestResultUtil.data(restResult, ProductDataTableForList.class);
        return data;
    }

    @Override
    public List<ProductDataTableForList> infosCurrentBySystemProductIds(FeignFindInfoBySystemProductIds feignFindInfoBySystemProductIds)
            throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        feignFindInfoBySystemProductIds.setHostId(requestHolder.getHost().getId()).setSiteId(requestHolder.getCurrentSite().getId());
        RestResult restResult = cProductFeign.findInfosBySystemProductIds(feignFindInfoBySystemProductIds);
        @SuppressWarnings("unchecked")
        List<ProductDataTableForList> data = (List<ProductDataTableForList>) RestResultUtil.data(restResult,
                new TypeReference<List<ProductDataTableForList>>() {
                });
        return data;
    }

    @Override
    public List<String> allLabelTitleByHostSiteSystemId(long systemId) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        long hostId = requestHolder.getHost().getId();
        long siteId = requestHolder.getCurrentSite().getId();
        RestResult restResult = sProductLabelFeign.allLabelTitleByHostSiteSystemId(hostId, siteId, systemId);
        @SuppressWarnings("unchecked")
        List<String> data = (List<String>) RestResultUtil.data(restResult, new TypeReference<List<String>>() {
        });
        return data;
    }

    @Override
    public boolean updateLabelTitleByHostSiteSystemId(long systemId, String otitle, String ntitle)
            throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        long hostId = requestHolder.getHost().getId();
        long siteId = requestHolder.getCurrentSite().getId();
        RestResult restResult = sProductLabelFeign.updateLabelTitleByHostSiteSystemId(hostId, siteId, systemId, otitle, ntitle);
        Integer data = RestResultUtil.data(restResult, Integer.class);
        return data != null && data.intValue() > 1 ? true : false;
    }

    @Override
    public int totalByHostId() throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        Long hostId = requestHolder.getCurrentSite().getId();
        return totalByHostId(hostId);
    }

    @Override
    public int totalByHostId(long hostId) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = sProductFeign.totalByHostId(hostId);
        Integer data = ResultUtil.data(restResult, Integer.class);
        if (data == null) {
            return 0;
        }
        return data.intValue();
    }

    @Override
    public int totalByHostSystemId(long systemId) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        Long hostId = requestHolder.getCurrentSite().getId();
        return totalByHostSystemId(hostId, systemId);
    }

    @Override
    public int totalByHostSystemId(long hostId, long systemId) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        FeignSystemTotal feignSystemTotal = new FeignSystemTotal();
        feignSystemTotal.setHostId(hostId).setSystemId(systemId);
        RestResult restResult = sProductFeign.totalByFeignSystemTotal(feignSystemTotal);
        Integer data = ResultUtil.data(restResult, Integer.class);
        if (data == null) {
            return 0;
        }
        return data.intValue();
    }

//	@Override
//	public List<SProduct> findInfosByHostSiteSystemAndIds(FeignSystemDataInfos feignSystemDataInfos)
//			throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
//		RestResult restResult = sProductFeign.findInfosByHostSiteSystemAndIds(feignSystemDataInfos);
//		@SuppressWarnings("unchecked")
//		List<SProduct> listSProduct = (ArrayList<SProduct>) RestResultUtil.data(restResult, new TypeReference<ArrayList<SProduct>>() {
//		});
//		return listSProduct;
//	}

    @Override
    public boolean cleanRecycle(List<SProduct> listSProduct) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = cProductFeign.cleanRecycle(listSProduct);
        return RestResultUtil.data(restResult, Boolean.class);
    }

    @Override
    public boolean cleanRecycleAll(SSystem sSystem) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = cProductFeign.cleanRecycleAll(sSystem);
        return RestResultUtil.data(restResult, Boolean.class);
    }

    @Override
    public boolean reductionRecycle(List<SProduct> listSProduct) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = cProductFeign.reductionByListSProduct(listSProduct);
        return RestResultUtil.data(restResult, Boolean.class);
    }

//	@Override
//	public SProduct findByIdAndHostSiteSystemId(long id, long hostId, long siteId, long systemId) throws IOException {
//		RestResult restResult = sProductFeign.findByIdAndHostSiteSystemId(id, hostId, siteId, systemId);
//		return RestResultUtil.data(restResult, SProduct.class);
//	}

    protected void makeCustomLink(Product data, ItemCustomLink customLink) throws IOException {
        if (data != null) {
            if (customLink != null) {
                if (data.getSProduct() != null) {
                    SProduct dataSProduct = data.getSProduct();
                    if (dataSProduct.getId() != null) {
                        Long sProductId = dataSProduct.getId();
                        short status = customLink.getStatus();
                        List<String> path = customLink.getPath();
                        List<String> collect = path.stream().filter(StrUtil::isNotBlank).collect(Collectors.toList());
                        JsonResult saveItemCustomLink = systemItemCustomLinkServiceImpl.saveItemCustomLink(dataSProduct.getSystemId(), sProductId, status,
                                CollUtil.join(collect, "/"), "");
                        if (saveItemCustomLink.getCode() == 200) {
                            makeCustomLink(data);
                        }
                    }
                }
            }
        }
    }

    protected void makeCustomLink(Product data) throws IOException {
        if (data != null) {
            if (data.getSProduct() != null) {
                SProduct dataSProduct = data.getSProduct();
                if (dataSProduct.getId() != null) {
                    JsonResult itemCustomLink = systemItemCustomLinkServiceImpl.itemCustomLink(dataSProduct.getSystemId(), dataSProduct.getId());
                    if (itemCustomLink.getCode() == 200) {
                        Object dataObject = itemCustomLink.getData();
                        data.setCustomLink(dataObject);
                    }
                }
            }
        }
    }

}
